package com.gitee.kenewstar.migration.core;

import com.gitee.kenewstar.migration.entity.CommonDto;
import com.gitee.kenewstar.migration.entity.CommonResponse;
import com.gitee.kenewstar.migration.entity.CommonResult;
import com.gitee.kenewstar.migration.util.ReflectUtil;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author kenewstar
 */

@SuppressWarnings("all")
public abstract class AbstractSyncFunction<T> implements DataMigrationFunction {

    protected static final ThreadLocal<ContextParam> context = ThreadLocal.withInitial(ContextParam::new);

    @Override
    public CommonResponse migration(List<CommonDto> list) {
        try {
            return CommonResponse.result(this.execute(context.get(), this.processParams(list, this.parameterType())));
        } catch (Exception e) {
            throw new CommonException(e);
        } finally {
            context.remove();
        }
    }

    public <T> List<T> processParams(List<CommonDto> list, Class<T> tClass) {
        List<T> data = new ArrayList<>(list.size());
        List<Field> fields = ReflectUtil.getFields(tClass);

        list.forEach(dto -> {

            try {
                final T t = tClass.getConstructor().newInstance();
                final Field migrationCode = ReflectUtil.queryMigrationCode(fields);
                final Field migrationTenantId = ReflectUtil.queryMigrationTenantId(fields);
                Assert.notNull(migrationCode, "@MigrationCode不存在");
                migrationCode.setAccessible(Boolean.TRUE);
                migrationCode.set(t, dto.getMigrationCode());
                if (Objects.nonNull(migrationTenantId)) {
                    migrationTenantId.setAccessible(Boolean.TRUE);
                    migrationTenantId.set(t, dto.getMigrationTenantId());
                }
                data.add(t);
            } catch (Exception e) {
                e.printStackTrace();
                throw new IllegalArgumentException("数据转换失败");
            }

        });

        return data;
    }

    protected abstract Class<T> parameterType();

    public abstract List<CommonResult> execute(ContextParam contextParam, List<T> list);

}
